package com.oraycn.esbasic.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

/**
 * 带有分组的列表
 * @param <T>
 */
public abstract class SeparatorAdapter<T> extends BaseAdapter {
    protected List<T> dataList =new ArrayList<>();
    protected TreeSet<Integer> set = new TreeSet<Integer>();
    protected Context context;
    protected HashMap<Integer,Integer> layoutIdMap; //多种itemView时用到。 第一个int对应type类型，第二个int对应 itemlayoutId

    public SeparatorAdapter(Context _context) {
        this.context = _context;
    }

    /**
     * 设置多个子模版VIew， 并配合重写 getItemViewType(int position)来确定是设置哪个模版
     * @param layoutIdMap 多种itemViewID Map 第一个int对应type类型，第二个int对应 itemlayoutId
     */
    public void initLayoutIdMap(HashMap<Integer,Integer> layoutIdMap) {
        this.layoutIdMap = layoutIdMap;
    }

    @Override
    public int getViewTypeCount() {
        return this.layoutIdMap.size();
    }

    @Override
    public int getItemViewType(int position) {
        return this.getViewItemType(position);
    }

    @Override
    public int getCount() {
        return this.dataList.size();
    }

    @Override
    public Object getItem(int position) {
        return this.dataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        int type = getItemViewType(position);
        return getConvertView(position,convertView,type);
    }

    private View getConvertView(int position,View convertView,int itemViewType) {
        try {
            if (convertView == null) {
                int layoutId = 0;
                if (this.layoutIdMap != null) {
                    layoutId = this.layoutIdMap.get(itemViewType);
                }
                convertView = LayoutInflater.from(context).inflate(layoutId, null);
            }
            T t = this.dataList.get(position);
            this.setConvertView(convertView, t, itemViewType,position);
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }
        return convertView;
    }

    public void addItem(T item) {
        dataList.add(item);
    }

    public void addSeparatorItem(T item) {
        dataList.add(item);
        set.add(dataList.size() - 1);
    }

    public void remove(int position) {
        dataList.remove(position);
    }
    
    public void clear() {
        dataList.clear();
        set.clear();
    }

    /**
     * 设置初始数据  （数据源更新需重新绑定）
     * @param map
     */
    public void setDataList(HashMap<T,List<T>> map) {
        this.clear();
        for (Map.Entry<T, List<T>> kvp : map.entrySet()) {
            this.addSeparatorItem(kvp.getKey());
            for (T item : kvp.getValue()) {
                this.addItem(item);
            }
        }
    }

    /**
     * 局部更新数据，调用一次getView()方法；Google推荐的做法
     *
     * @param parent  要更新的listview
     * @param position 要更新的位置
     */
    public void onOneItemChanged(ListView parent, int position) {
        /**第一个可见的位置**/
        int firstVisiblePosition = parent.getFirstVisiblePosition();
        /**最后一个可见的位置**/
        int lastVisiblePosition = parent.getLastVisiblePosition();

        /**在看见范围内才更新，不可见的滑动后自动会调用getView方法更新**/
        if ((position >= firstVisiblePosition && position <= lastVisiblePosition)) {

            /**获取指定位置view对象**/
            View view = parent.getChildAt(position - firstVisiblePosition);
            getView(position, view, parent);
        }
    }

    /**
     * 需要去实现的对item中的view的设置操作
     *
     * @param convertView 转换后的试图
     * @param t Model对象
     * @param itemViewType 试图类型。对应layoutIdMap中的key
     */
    protected abstract void setConvertView(View convertView, T t,int itemViewType,int position);

    /**
     * 重写 getItemViewType(int position)来确定是设置哪个模版
     * @param position
     * @return View模版ID
     */
    protected abstract int getViewItemType(int position) ;
}
